:- use_module(library(lists)).
:- use_module(library('clp/bounds')).
%:- use_module(library(clp/clp_distinct)).

:- consult(conditions).
:- consult(arr_fnc).

% path(N brigade, N from, N to, path time)
path(Br,0,B,T) :- 
	at(Br,AT), 
	ht(Br,B,HT), 
	T #= AT + HT.

path(Br,A,B,T) :- 
	ht(Br,A,HT1), 
	ht(Br,B,HT2), 
	T #= HT1 + HT2.

% store path to list [A,B,T]
step(Br,A,B,T,[A,B,T]) :- path(Br,A,B,T).

route(_,X,X,0,[],HC,HC,0).

% route(N brigade, N from, N to, path time, Ps - edges list, HC - total quantity of patients delivered to each hospital before this route, HC - total quantity of patients delivered to each hospital after this route, Pq - number of patients)
% the path through points: X,Z,Y
route(Br,X,Y,T,Ps,HC,HCnew,Pq) :- 
	%write('FIND ROUTE'),nl,
	Pq #> 0, Pq1 #= Pq - 1,
	route(Br,X,Z,T1,Ps1,HC,HC1,Pq1),
	step(Br,Z,Y,T2,Ps2),
	inc_arr(Y,_,HC1,HCnew),
	nth1(Y,HCnew,Hc1),
	hc(Y,Hc2),
	Hc1 =< Hc2,
	T #= T1 + T2,
	solution(BT,_,_),
	T < BT,
	Ps = [Ps1|Ps2].


way(Br):- write('Br: '),write(Br),nl,
	pat_alloc(PQARR),
	%label(PQARR),
	write('PQARR: '),write(PQARR),nl,
	nth1(Br,PQARR,Pq),
	write('Pq: '),write(Pq),nl,
	retract(hosp_fill(HC)),
	write('HC: '),write(HC),nl,
	retract(times(TARR)),
	write('TARR: '),write(TARR),nl,
	%nth1(Br,TARR,T),
	retract(pathes(PsARR)),
	write('PsARR: '),write(PsARR),nl,
	route(Br,0,_,T,Ps,HC,HCnew,Pq),
	write('HCnew: '),write(HCnew),nl,
	assert(hosp_fill(HCnew)),
	set_arr(Br,TARR,T,TARRnew,_),
	assert(times(TARRnew)),
	write('TARRnew: '),write(TARRnew),nl,
	set_arr(Br,PsARR,Ps,PsARRnew,_),
	write('PsARRnew: '),write(PsARRnew),nl,
	assert(pathes(PsARRnew)).
	
way_for_all([]):-!.

way_for_all(List):- write('List: '),write(List),nl,
	List = [Br|List1],
	way(Br),
	way_for_all(List1).

%mutual(T - max time for all brigades, Ps - edges list of all brigades, HC - total quantity of patients delivered to each hospital, PQ - sum of patients)
%example: mutual(T,Ps,HC,2).
mutual:-
	nl,write('MUTUAL'),nl,
	problem_size(Br,H,PQ),
	length(PQARR,Br),
	create_arr(HC,H),
	assert(hosp_fill(HC)),
	%vars_in(PQARR,0,PQ),
	PQARR in 0..PQ,
	sum(PQARR,#=,PQ),
	label(PQARR),
	assert(pat_alloc(PQARR)),
	
	numlist(1,Br,Br_numbers),
	way_for_all(Br_numbers),
	write('AFTER ALL WAYS'),nl,

	times(TARR),
	msort(TARR,TARRsort),
	last(TARRsort,T),
	write('TARR and T: '),write(TARR),write(T),nl,
	pathes(Ps),
	write('Ps: '),write(Ps),nl,
	retract(solution(_,_,_)),
	write('Retract old solution'),nl,
	retract(hosp_fill(HCnew)),
	write('Retract HCnew'),write(HCnew),nl,
	asserta(solution(T,Ps,HCnew)),
	fail.

% solve(TE - total time, PS - list of routs for brigades ([route of Br1 # rout of Br2]), HC - total quantity of patients delivered to each hospital, PQ - number of patients to save)
% example: solve(TE,PS,HC).
solve(TE,PS,HC):- 
	asserta(solution(100000,ps,hc)),
	problem_size(Br,_,_),
	create_arr(TARR,Br),
	asserta(times(TARR)),
	length(PsARR,Br),
	init_arr(PsARR,[]),
	asserta(pathes(PsARR)),
	not(mutual),
	retract(solution(TE,Ps,Hc)),
	flatten(Ps,PS),
	flatten(Hc,HC).


































